package com.example.client.netty;

import com.example.commons.*;
import com.example.commons.future.MsgFuture;
import com.example.commons.handler.AbstractMsgHandler;
import com.example.commons.handler.HandlerRegister;
import com.example.commons.model.BizReqMsg;
import com.example.commons.model.BizResMsg;
import com.example.commons.model.LoginResMsg;
import io.netty.channel.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.TimeUnit;

/**
 * @author cdw
 * <p>
 * 客户端处理器
 **/
@Slf4j
@Component
@ChannelHandler.Sharable
public class NettyClientHandler extends ChannelInboundHandlerAdapter {

    @Autowired
    private NettyClient client;

    @Autowired
    private MsgPool pool;

    /**
     * 业务处理线程池，防止业务响应慢阻塞通讯线程
     */
    @Autowired
    private ExecutorService executor;

    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        log.info("客户端Active .....");
    }

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        Channel channel = ctx.channel();

        executor.execute(() -> {
            if (msg instanceof LoginResMsg) {
                log.info("客户端收到【登录结果】消息: {}", msg.toString());
                pool.setServerChannel(channel);
            } else if (msg instanceof BizReqMsg) {
                log.info("server -> client 回应 [{}]", msg);
                BizReqMsg bizReqMsg = (BizReqMsg) msg;
                BizResMsg bizResMsg = new BizResMsg();
                bizResMsg.setReqId(bizReqMsg.getReqId());

                AbstractMsgHandler msgHandler = HandlerRegister.getHandler(bizReqMsg.getCmd());
                if (msgHandler == null) {
                    msgHandler = HandlerRegister.getHandler(MsgPool.DEFAULT_CMD);
                }
                AbstractMsgHandler finalMsgHandler = msgHandler;
                Object result = finalMsgHandler.execute(bizReqMsg.getData());
                bizResMsg.setResult(result);
                ctx.writeAndFlush(bizResMsg);

            } else if (msg instanceof BizResMsg) {
                log.info("client -> server 返回 [{}]", msg);

                BizResMsg bizResMsg = (BizResMsg) msg;
                MsgFuture future = pool.get(bizResMsg.getReqId());
                if (future != null) {
                    future.setRes(bizResMsg);
                }
            } else {
                log.info("客户端收到消息: {}", msg.toString());
            }
        });

    }

    @Override
    public void channelInactive(ChannelHandlerContext ctx) {
        log.info("与服务器连接断开，启动重连");
        final EventLoop eventLoop = ctx.channel().eventLoop();
        eventLoop.schedule(() -> client.connect(), 1L, TimeUnit.SECONDS);
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        cause.printStackTrace();
        ctx.close();
    }
}